package com.tinfeng.uplevel;

import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;

import java.io.*;

public class JavaSerialize {
    // java 序列化
    // Java 语言提供自动序列化，序列化（serialize）就是将对象转换为字节流；
    // 与之相应对的，反序列化（deserialize）就是将字节流转换为对象。

    // Java 序列化对象时，会把对象的状态保存成字节序列，对象的状态指的就是其成员变量，因此序列化的对象不会保存类的静态变量。

    // 可通过输入\输出流来序列\反序列对象，ObjectInputStream类 和 ObjectOutputStream类

    /**
     *
     * 序列化的作用
     * 序列化可以将对象的字节序列存持久化：可以将其保存在内存、文件、数据库中（见下图）；
     * 可以在网络上传输对象字节序列；
     * 可用于远端程序方法调用
     * */
    // 将对象转为字节序列，可以存到内存、文件、数据库，还可通过网络传输，提供远程方法调用，最后在转为对象

    static class Cat implements Serializable {
        private static final  long serialVersionUID = 1L;
        // erialVersionUID 是 Java 为每个序列化类产生的版本标识。它可以用来保证在反序列化时，发送方发送的和接受方接收的是可兼容的对象
        // 不一致会抛出异常

        private String nickname;

        private Integer age;

        // 构建函数
        public Cat() {

        }

        public Cat(String nickname,Integer age) {
            this.nickname = nickname;
            this.age = age;
        }

        @Override
        public String toString() {
            return "Cat{" +
                    "nickname='" + nickname + '\'' +
                    ", age=" + age +
                    '}';
        }

    }
    // 序列化方法
    private static void serialize(String filepath,Cat cat) throws IOException {
        // 实例化file对象
        File file = new File(filepath);
        // 实例化文件输出流
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        // 实例化对象输出流
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        // 保存cat对象
        objectOutputStream.writeObject(cat);
        // 关闭流
        fileOutputStream.close();
        objectOutputStream.close();
    }

    // 反序列化方法
    private static void deserialize(String filepath) throws IOException,ClassNotFoundException {
        // 实例化file
        File file = new File(filepath);
         // 实例化文件输入流
        FileInputStream fileInputStream = new FileInputStream(file);
        // 实例化对象输入流
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

        Object o = objectInputStream.readObject();
        System.out.println(o);
    }
    public static void main(String[] args) throws IOException,ClassNotFoundException{
        // ObjectOutputStream 类下的void writeObject(Object obj) 是将对象写入对象输出流，序列化

        // ObjectInputStream类 下的Object readObject()方法用于读取一个对象到输入流 ，反序列化

        String filename = "C:\\Users\\U\\Desktop\\work_file\\hello.txt";
        Cat cat = new Cat("猪皮", 1);
        serialize(filename,cat);
        deserialize(filename);
    }
    // 注意事项:
    // 被序列化的类必须是Enum、Array或Serializable中的任意一种类型。
    //
    //如果要序列化的类不是枚举类型和数组类型的话，则必须实现java.io.Seralizable接口，否则直接序列化将抛出NotSerializableException异常。

    // 好用的序列化工具
    // thrift、protobuf - 适用于对性能敏感，对开发体验要求不高的内部系统。
    // hessian - 适用于对开发体验敏感，性能有要求的内外部系统。
    // jackson、gson、fastjson - 适用于对序列化后的数据要求有良好的可读性（转为 json 、xml 形式）
}
